package kevin.study.zephyr.domain.model.view.soda;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;

import kevin.study.zephyr.domain.dao.soda.ZConstraint;
import kevin.study.zephyr.domain.dao.soda.ZQuery;
import kevin.study.zephyr.domain.model.Document;
import kevin.study.zephyr.domain.model.Entity;
import kevin.study.zephyr.domain.model.Field;
import kevin.study.zephyr.domain.model.Form;
import kevin.study.zephyr.domain.model.Item;
import kevin.study.zephyr.domain.soda.Constraint;
import kevin.study.zephyr.domain.soda.Constraints;
import kevin.study.zephyr.domain.soda.Query;


/**
 * @author Kevin.Huang
 * @createtime 2007-12-12
 */
public class VQuery implements Query {

	/**
	 * Root
	 */
	private ZQuery zQuery;

	/**
	 * Currently
	 */
	private ZConstraint currentZConstraint;

	private String field;

	private int deep;

	private Collection< ZConstraint > constraints = new ArrayList< ZConstraint >();

	public VQuery() {
		super();
		deep = 0;
		zQuery = new ZQuery();
	}

	protected VQuery(ZQuery rootQuery, ZConstraint currentConstraint, String field, int deep) {
		this.zQuery = rootQuery;
		this.currentZConstraint = currentConstraint;
		this.field = field;
		this.deep = deep + 1;

	}

	public Constraint constrain(Object constraint) {
		// deep为0时为根节点,此节点为约束Form用
		ZConstraint returnConstraint;
		if (deep == 0) {
			if (constraint instanceof Form) {
				returnConstraint = (ZConstraint) zQuery.descend(Document.FILTER_FORM).constrain(constraint);
			} else if (constraint instanceof String) {
				returnConstraint = (ZConstraint) zQuery.descend(Document.FILTER_FORM).descend(
						Form.FILTER_NAME).constrain(constraint);
			} else {
				throw new RuntimeException("Not Support this object TYPE!");
			}
		} else {
			returnConstraint = (ZConstraint) zQuery.descend(Document.FILTER_ITEMS)
					.descend(Item.FILTER_ENTITY).descend(Entity.FILTER_VALUE).constrain(constraint);
			currentZConstraint.and(returnConstraint);
		}
		constraints.add(returnConstraint);
		return new VConstraint(currentZConstraint, returnConstraint);
	}

	public Constraints constraints() {
		return new VConstraints(this.constraints);
	}

	public Query descend(String fieldName) {
		return new VQuery(this.zQuery, (ZConstraint) zQuery.descend(Document.FILTER_ITEMS).descend(
				Item.FILTER_FIELD).descend(Field.FILTER_NAME).constrain(fieldName).equal(), fieldName,
				this.deep);
	}

	public Query orderAscending() {
		this.zQuery.sortBy(new Comparator< Document >() {
			public int compare(Document o1, Document o2) {
				return o1.compareTo(o2, field);
			}
		});
		return this;
	}

	public Query orderDescending() {
		this.zQuery.sortBy(new Comparator< Document >() {
			public int compare(Document o1, Document o2) {
				return o2.compareTo(o1, field);
			}
		});
		return this;
	}

	/**
	 * @return the zQuery
	 */
	public ZQuery getZQuery() {
		return zQuery;
	}

}
